package com.qjq.glasses_shopping.util;

import lombok.SneakyThrows;
import org.jose4j.json.JsonUtil;
import org.jose4j.jwa.AlgorithmConstraints;
import org.jose4j.jwk.RsaJsonWebKey;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;

public class JwtUtils {
  // 私钥
  public final static String PRIVATE_JSON = "{\"kty\":\"RSA\",\"n\":\"ylRV3S0VfOkG4EOfUNpaLpoeGCOt_Cbhhp1KYeWbc5Y5ZlJSTu17RQt5aEZlfoj-3DFimCZcDEsiFIqY_FwHU1L-5z051Q7JCvFVSKTLGQR0jCHfxhxR0YSDiTCxAShX-gfYxGEi2uKAqSEKG9xWkTEdsNaJQwEmyFPmc6jwkGPAnB5R_AvvMkYzCk6zgjdbm3VDB28aLGyCJFhuYcVml3v3M10SEyPganKdGsZOqVR3Grm0m239C32N6uYB5Cpl_J5e2pukGMozpkCCQ7Foe3DINrMlQl-_5IowU5mKRwc9muieJw--FM5HqLyVM0tLPz0OCBctQkk2JmHY3PqpWQ\",\"e\":\"AQAB\",\"d\":\"Zj8kXdATIViwPKxczY1g6Tmsgv8TmQ6AawdLf1y561sxH1BgdyMAhV0M1zrRAfNRaw1Es5vpwZpNhPvO9J_WpKcurQg4zWSB9JLTzC5Ah5GiQVJ2LugXYiTbDtD3-mWmRofTO6mAszKnUT4tK8aq8k7ifk2QG6cUEkCjuuM7jSyugtuqkUJFzzeD6bzMRdyXk3-brUSoOFWKaIjg0AflABpcEIdIKO3WZnUwu2kcmZDGTMFbnu2PXKhwCkJ3GTh5bBkMX-HqmPW3vMgCT2UEXM9wrx_uzwv3E7ajkFHCFndYQl0A8Mec8coc6K10nPWqgTnyEGzNu4qjp-3BuNLB\",\"p\":\"42ltrrFyP7hQWCcGmDHQIwhoKIQXnm-AMouipAF-hbN8LRKlQQJRHFH-Gy0LIQSi2Qh8xrjjS9VmE-ed75ECqYybkSdr-VEmNjMKLtgKlkhnnB8U3po9un9KnM-R25eBE_77tGAc7NtBcBcmTp_scyUDAo4qF6GUaKc3w21-VkE\",\"q\":\"48O0c35LcyAfrw52EMJBAcDJNUTzMWCog_41xu5161wFoUFNSxlqfZHCDJWbuqtct2KPSgG31bY78iIt0lW5J-onGsxcvvGvCU9FcQoPzf0GcLmW-x6HVLAol2QkujxCvKH9TVEFkQ7PMV2rLOuzYWRIt2wrGkmJGMVYq1Lm_Rk\",\"dp\":\"3WQ0LY_-w93yCf_kQaKtGI4EqPz_6XRvf8XFDpmNzSgRSegPDZztzf5cvaQ6Y2iaCWRj5Sr1zUvxVot0jFfGGb4TbVrNmSjRZI6H6VbV57yRccIolRXf5oIp50OEoh16wjbIYK_5OPWzXSaMWpsCnI55wbEZdWwOiVvRw-YCyoE\",\"dq\":\"bd3QZMmuIXmEbw_9ubXKX8scA7sfyFjE0O7GCBCtBvwbpx5151z6NloiDan5NcFFdxxu3BcaE1fVcMY17jj1mKBlfpLHxj-U3FvFtnJRD18XRTbw8m9Wfm5_Fg_ze3ZoBs_o_OuxULihD0IMuR11KOyT-w6NeB-ypyVC0VmrHLk\",\"qi\":\"CFHvhJaYMZAb5qlNlJU6-LC3WG9u6WBjdE1CjMNqeYgB1d--ICGT7vl3IPACkCmC3_za1ktVH4M_09XvS8bOaM2-DBVSZiTcz-atcA3vnnAowMsFLwpPvuR7EzSy_hps7KC53fhVre8ydjMnZ5ue3y7uffIUgzZq_h8AIhm7D8M\"}";
  // 公钥
  public final static String PUBLIC_JSON = "{\"kty\":\"RSA\",\"n\":\"ylRV3S0VfOkG4EOfUNpaLpoeGCOt_Cbhhp1KYeWbc5Y5ZlJSTu17RQt5aEZlfoj-3DFimCZcDEsiFIqY_FwHU1L-5z051Q7JCvFVSKTLGQR0jCHfxhxR0YSDiTCxAShX-gfYxGEi2uKAqSEKG9xWkTEdsNaJQwEmyFPmc6jwkGPAnB5R_AvvMkYzCk6zgjdbm3VDB28aLGyCJFhuYcVml3v3M10SEyPganKdGsZOqVR3Grm0m239C32N6uYB5Cpl_J5e2pukGMozpkCCQ7Foe3DINrMlQl-_5IowU5mKRwc9muieJw--FM5HqLyVM0tLPz0OCBctQkk2JmHY3PqpWQ\",\"e\":\"AQAB\"}\n";


  /**
   * 生成token
   *
   * @param userId    用户id
   * @param username 用户名字
   * @return
   */
  @SneakyThrows
  public static String sign(Long userId, String username) {
    // 1、 创建jwtclaims  jwt内容载荷部分
    JwtClaims claims = new JwtClaims();
    // 是谁创建了令牌并且签署了它
    claims.setIssuer("郄军强");
    // 令牌将被发送给谁
    claims.setAudience("audience");
    // 失效时间长 （分钟）
    claims.setExpirationTimeMinutesInTheFuture(60 * 24);
    // 令牌唯一标识符
    claims.setGeneratedJwtId();
    // 当令牌被发布或者创建现在
    claims.setIssuedAtToNow();
    // 再次之前令牌无效
    claims.setNotBeforeMinutesInThePast(2);
    // 主题
    claims.setSubject("shopping");
    // 可以添加关于这个主题得声明属性
    claims.setClaim("userId", userId);
    claims.setClaim("username", username);


    // 2、签名
    JsonWebSignature jws = new JsonWebSignature();
    //赋值载荷
    jws.setPayload(claims.toJson());


    // 3、jwt使用私钥签署
    PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(PRIVATE_JSON)).getPrivateKey();
    jws.setKey(privateKey);


    // 4、设置关键 kid
    jws.setKeyIdHeaderValue("keyId");


    // 5、设置签名算法
    jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
    // 6、生成jwt
    String jwt = jws.getCompactSerialization();
    return jwt;
   }




  /**
   * 解密token，获取token中的信息
   *
   * @param token
   */
  @SneakyThrows
  public static Map<String, Object> verify(String token){
    // 1、引入公钥
    PublicKey publicKey = new RsaJsonWebKey(JsonUtil.parseJson(PUBLIC_JSON)).getPublicKey();
    // 2、使用jwtcoonsumer  验证和处理jwt
    JwtConsumer jwtConsumer = new JwtConsumerBuilder()
         .setRequireExpirationTime() //过期时间
         .setAllowedClockSkewInSeconds(30) //允许在验证得时候留有一些余地 计算时钟偏差  秒
         .setRequireSubject() // 主题生命
         .setExpectedIssuer("郄军强") // jwt需要知道谁发布得 用来验证发布人
         .setExpectedAudience("audience") //jwt目的是谁 用来验证观众
         .setVerificationKey(publicKey) // 用公钥验证签名  验证密钥
         .setJwsAlgorithmConstraints(new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.WHITELIST, AlgorithmIdentifiers.RSA_USING_SHA256))
         .build();
    // 3、验证jwt 并将其处理为 claims
    try {
      JwtClaims jwtClaims = jwtConsumer.processToClaims(token);
      return jwtClaims.getClaimsMap();
     }catch (Exception e){
      return new HashMap();
     }
   }




  public static void main(String[] args){
    // 生成
    String str = sign(1001L, "qjq");
    System.out.println(str);


    Map<String, Object> stringObjectMap = verify(str);
    System.out.println(stringObjectMap.get("userId"));
    System.out.println(stringObjectMap.get("username"));
   }
}
